<template>
  <div>
  <a-spin :spinning="spinning != 0">
    <a-input-search v-model="searchText" @search="onSearch" style="width:100%;" placeholder=""/>
    <a-tree
      :showLine="true"
      :tree-data="treeData"
      :load-data="onLoadData"
      :checkStrictly="!checkableLinkage || !checkable || !multi"
      :checkable="checkable"
      :checkedKeys="checkedKeys"
      @check="onCheck"
      @select="onSelect"
      :expandedKeys.sync="expandedKeys"
      :selectedKeys="selectedKeys"
      :replaceFields="replaceFields"
    >
      <template slot="title" slot-scope="record">
        <span :title="record.orgName" v-if="orgTreeShowDeptAbbr && record.orgNameAbbr">{{record.orgNameAbbr}}</span>
        <span :title="record.orgName" v-else>{{record.orgName}}</span>
      </template>
    </a-tree>
  </a-spin>
  </div>
</template>

<script>

  import { postAction } from '@/api/manage'
  import YchOrg from "@/api/YchOrg"

  export default {
    name: 'SysOrgTree',
    props: {
      checkable: {
        type: Boolean,
        default: false
      },
      value: {
        type: Array,
        default: () => []
      },
      multi: {
        type: Boolean,
        default: false
      },
      selectedRoot: {
        type: Boolean,
        default: false
      },
      currentOrgAsRoot:{
        type:Boolean,
        default:false
      },
      filterAuth:{
        type:Boolean,
        default:false
      },
      isResetOrg:{
        type:Boolean,
        default:false
      },
      checkableLinkage:{
        type:Boolean,
        default:false
      },
      onlyCheckDept:{
        type:Boolean,
        default:false
      },
      orgTreeShowDeptAbbr:{
        type:Boolean,
        default:false
      },
      deptId: String, // 指定了根节点
      customOrgOrderSql: String, // 自定义组织树排序Sql
      customOrgFilterSql: String, // 自定义组织树过滤Sql
      checkBySelect:{
        type:Boolean,
        default:false
      }
    },
    computed: {
      checkedKeys() {
        return {
          checked: this.value.map(item => item.id)
        }
      }
    },
    watch: {
      isResetOrg(val) {
        if(val==true){
          this.selectedKeys = []
        }
      },
      value: {
        immediate: true,
        handler(val) {
          if(val && val.length>0){
            this.checkedRows = val.map(item=>{
              return {
                id:item.id,
                orgName:item.orgName,
                orgNameAbbr:item.orgNameAbbr
              }
            })
          }else{
            this.checkedRows = []
          }
        }
      },
      deptId: {
        handler() {
          this.loadData()
        }
      },
    },
    data() {
      return {
        spinning: 0,
        treeData: [],
        expandedKeys: [],
        searchText: null,
        selectedKeys: [],
        checkedRows:[],
        replaceFields: {
          children: 'children', title: 'orgName', key: 'id'
        },
        url: {
          queryRootTreeList: YchOrg.queryOrgRootTreeList+"?currentOrgAsRoot="+this.currentOrgAsRoot+"&filterAuth="+this.filterAuth+"&onlyCheckDept="+this.onlyCheckDept,
          querySubTreeList: YchOrg.queryOrgSubTreeList+"?filterAuth="+this.filterAuth+"&onlyCheckDept="+this.onlyCheckDept,
          queryTreeListBatch: YchOrg.queryOrgTreeListBatch+"?filterAuth="+this.filterAuth+"&onlyCheckDept="+this.onlyCheckDept,
          searchTreeList: YchOrg.searchOrgTreeList+"?currentOrgAsRoot="+this.currentOrgAsRoot+"&filterAuth="+this.filterAuth+"&onlyCheckDept="+this.onlyCheckDept,
          getAllSubOrgListByOrgIds:YchOrg.getAllSubOrgListByOrgIds+"?filterAuth="+this.filterAuth,
        }
      }
    },
    created() {
      this.loadData()
    },
    methods: {
      onSelect(selectedKeys, e) {
        if (selectedKeys.length == 0) {
          return
        }
        this.selectedKeys = selectedKeys
        this.$emit('onSelect', this.selectedKeys[0], e.node.dataRef.orgCode)
        //select 选中可以触发check
        if(this.checkBySelect && e.node.dataRef.checkable){
          this.checkForSelect(selectedKeys,e)
        }
      },
      checkForSelect(selectedKeys, e){
        const selectedKey = selectedKeys[0]
        let exists = this.checkedKeys.checked.filter(item=>item==selectedKey)
        if(exists.length<1){
          const checkedNode = {
            id: e.node.dataRef.id, orgName: e.node.dataRef.orgName, orgNameAbbr: e.node.dataRef.orgNameAbbr, orgCode: e.node.dataRef.orgCode
          }
          if (this.multi){
            this.checkedKeys.checked.push(selectedKey)
            let existsRows = this.checkedRows.filter(item=>item.id==selectedKey)
            if(existsRows<1){
              this.checkedRows.push(checkedNode)
            }
            //关联下级
            if(this.checkableLinkage){
              let parentIdList = this.checkedRows.map(item=>{
                  return item.id
                }
              )
              let parentIds = parentIdList.join(",")
              this.spinning++
              postAction(this.url.getAllSubOrgListByOrgIds + "&parentIds=" + (parentIds || ''), {customOrgOrderSql: this.customOrgOrderSql, customOrgFilterSql: this.customOrgFilterSql}).then((res) => {
                if (res.success) {
                  let result = res.result || []
                  let subOrgList = result.map(item => {
                    return {id: item.id, orgName: item.orgName, orgNameAbbr: item.orgNameAbbr, orgCode: item.orgCode}
                  })
                  let allCheckedRows = [...this.checkedRows,...subOrgList]
                  //去重
                  const uniMap = new Map();
                  allCheckedRows =  allCheckedRows.filter((row) => !uniMap.has(row.id) && uniMap.set(row.id, 1));
                  this.checkedRows = allCheckedRows
                  this.$emit('input', allCheckedRows)
                } else {
                  this.messageUtil.warning(res.message)
                }
              }).finally(() => {
                this.spinning--
              })
            }else{
              this.$emit('input', this.checkedRows)
            }
          }else{
            this.checkedKeys.checked[0] = selectedKey
            this.checkedRows = [checkedNode]
            this.$emit('input', this.checkedRows)
          }

        }
      },
      loadData() {
        this.spinning++
        let url = this.url.queryRootTreeList;
        if (this.deptId) {
          // 指定了根节点
          url += "&deptId=" + this.deptId
        }
        postAction(url, {customOrgOrderSql: this.customOrgOrderSql, customOrgFilterSql: this.customOrgFilterSql}).then((res) => {
          if (res.success) {
            this.treeData = res.result || []
            if (this.treeData.length > 0 && this.expandedKeys.indexOf(this.treeData[0].id) == -1 && !this.treeData[0].isLeaf) {
              this.expandedKeys = [...this.expandedKeys, this.treeData[0].id]
            }
            //根节点选择多个部门时不再查询下级，部门关联用户部门多选的情况
            if(!(this.deptId && this.deptId.indexOf(",")>-1)){
              this.loadDataByExpandedRows(this.treeData)
            }
            if (this.treeData.length > 0 && this.selectedRoot) {
              this.selectedKeys = [this.treeData[0].id]
              this.$emit('onSelect', this.selectedKeys[0], this.treeData[0].orgCode)
            }
          } else {
            this.messageUtil.warning(res.message)
          }
        }).finally(() => {
          this.spinning--
        })
      },
      loadDataByExpandedRows(dataList) {
        if (this.expandedKeys.length > 0) {
          this.spinning++
          const url = this.url.queryTreeListBatch + "&parentIds=" + this.expandedKeys.join(',')
          postAction(url, {customOrgOrderSql: this.customOrgOrderSql, customOrgFilterSql: this.customOrgFilterSql}).then((res) => {
            if (res.success) {
              const childrenMap = res.result
              const fn = (list) => {
                if (list == null) {
                  return
                }
                list.forEach(data => {
                  if (this.expandedKeys.includes(data.id)) {
                    data.children = childrenMap[data.id]
                    fn(data.children)
                  }
                })
              }
              fn(dataList)
            } else {
              this.messageUtil.warning(res.message)
            }
          }).finally(() => {
            this.spinning--
          })
        }
      },
      onLoadData(treeNode) {
        return new Promise(resolve => {
          if (treeNode.dataRef.children && treeNode.dataRef.children.length > 0) {
            resolve()
            return
          }
          this.spinning++
          postAction(this.url.querySubTreeList + "&parentId=" + treeNode.dataRef.id, {customOrgOrderSql: this.customOrgOrderSql, customOrgFilterSql: this.customOrgFilterSql}).then((res) => {
            if (res.success) {
              treeNode.dataRef.children = res.result || []
              this.treeData = [...this.treeData]
              resolve()
            } else {
              this.messageUtil.warning(res.message)
            }
          }).finally(() => {
            this.spinning--
          })
        })
      },
      onSearch(value) {
        if (value) {
          this.spinning++
          let url = this.url.searchTreeList;
          if (this.deptId) {
            // 指定了根节点
            url += "&deptId=" + this.deptId
          }
          url += "&orgName=" + (value || '')
          postAction(url, {customOrgOrderSql: this.customOrgOrderSql, customOrgFilterSql: this.customOrgFilterSql}).then((res) => {
            if (res.success) {
              this.treeData = res.result || []
              this.expandedKeys = []
              this.setExpandedKeys(this.treeData)
            } else {
              this.messageUtil.warning(res.message)
            }
          }).finally(() => {
            this.spinning--
          })
        } else {
          this.loadData()
        }
      },
      setExpandedKeys(treeData) {
        treeData.forEach(item => {
          if (item.children) {
            this.expandedKeys.push(item.id)
            this.setExpandedKeys(item.children)
          }
        })
      },
      onCheck(checkedKeys, info) {
        if (this.multi) {
          const checkedRows = info.checkedNodes.map(item => {
            return {id: item.key, orgName: item.data.props.orgName, orgNameAbbr: item.data.props.orgNameAbbr, orgCode: item.data.props.orgCode}
          })
          //关联下级
          if(this.checkableLinkage){
            let parentIdList = checkedRows.map(item=>{
                return item.id
              }
            )
            let parentIds = parentIdList.join(",")
            this.spinning++
            postAction(this.url.getAllSubOrgListByOrgIds + "&parentIds=" + (parentIds || ''), {customOrgOrderSql: this.customOrgOrderSql, customOrgFilterSql: this.customOrgFilterSql}).then((res) => {
              if (res.success) {
                let result = res.result || []
                let subOrgList = result.map(item => {
                  return {id: item.id, orgName: item.orgName, orgNameAbbr: item.orgNameAbbr, orgCode: item.orgCode}
                })
                let allCheckedRows = [...checkedRows,...subOrgList]
                //去重
                const uniMap = new Map();
                allCheckedRows =  allCheckedRows.filter((row) => !uniMap.has(row.id) && uniMap.set(row.id, 1));
                this.checkedRows = allCheckedRows
                this.$emit('input', allCheckedRows)
              } else {
                this.messageUtil.warning(res.message)
              }
            }).finally(() => {
              this.spinning--
            })
          }else{
            this.checkedRows = checkedRows
            this.$emit('input', checkedRows)
          }

        } else {
          const keys = checkedKeys.checked.filter(id => this.checkedKeys.checked.indexOf(id) == -1)
          const checkedRows = []
          info.checkedNodes.forEach(item => {
            if (keys.indexOf(item.key) != -1) {
              checkedRows.push({id: item.key, orgName: item.data.props.orgName, orgNameAbbr: item.data.props.orgNameAbbr, orgCode: item.data.props.orgCode})
            }
          })
          this.checkedRows = checkedRows
          this.$emit('input', checkedRows)
        }
      }
    }
  }
</script>
